package com.hanfu.ucenter.web.web.util;

import com.alibaba.fastjson.JSON;
import com.hanfu.ucenter.web.exception.UCenterException;
import com.hanfu.ucenter.web.web.param.union.UnionDto;
import com.hanfu.ucenter.web.web.vo.union.UnionResp;
import net.sf.json.JSONObject;
import org.apache.commons.codec.binary.Hex;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import sun.misc.BASE64Encoder;

import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.*;
import java.lang.reflect.Method;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;


/**
 * Created by dufei on 19/9/18.
 */
@Component
public class UnionUtil {

    private static final Logger logger = LoggerFactory.getLogger(UnionUtil.class);

    public static String accesser_id;

    public static String sign_type;

    public  static String preURL;

    public static String key;

    public static final String SYS_VAR_RAW_DATA = "rawData";


    @Value("${yinlian.accesser_id}")
    public  void setAccesser_id(String accesser_id) {
        UnionUtil.accesser_id = accesser_id;
    }

    @Value("${yinlian.sign_type}")
    public  void setSign_type(String sign_type) {
        UnionUtil.sign_type = sign_type;
    }

    @Value("${yinlian.preURL}")
    public  void setPreURL(String preURL) {
        UnionUtil.preURL = preURL;
    }

    @Value("${yinlian.sign_key}")
    public  void setKey(String key) {
        UnionUtil.key = key;
    }

    /**
     * 上传图片
     * @param dto
     */
    public static UnionResp execute(UnionDto dto, UnionResp resp) throws UCenterException {
        logger.info("dto {}",dto);
        Map<String, String>  map = sign(dto);
        Map<String,String> reqMap = new HashMap<>();
        reqMap.put("json_data",map.get("json_data"));
        reqMap.put("sign_data",map.get("sign_data"));
        reqMap.put("accesser_id",map.get("accesser_id"));
        logger.info("post yinlian is {}",reqMap);
        String json =   HttpClientUtil.httpPost(preURL,reqMap);
        logger.info("json code is {}",json);
        UnionResp unionResp =    jsonStrToDto(json,resp.getClass());
        if (!unionResp.getRes_code().equals("0000")) {
            throw new  UCenterException(unionResp.getRes_code(),unionResp.getRes_msg());
        }
        logger.info("resp is {}",unionResp);
        return unionResp;
    }

    /**
     * 获取map
     * @param dto
     * @return
     */
    public static Map getSrcMap(UnionDto dto) {
        Map<String, String>  srcMap = transBean2Map(dto);
        srcMap.put("accesser_id", accesser_id); //11
        srcMap.put("sign_type", sign_type);
        return srcMap;
    }

    /**
     * 构建map
     * @param obj
     * @return
     */
    public static Map<String, String> transBean2Map(Object obj) {

        if(obj == null){
            return null;
        }
        Map<String, String> map = new HashMap<String, String>();
        try {
            BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            for (PropertyDescriptor property : propertyDescriptors) {
                String key = property.getName();

                // 过滤class属性
                if (!key.equals("class")) {
                    // 得到property对应的getter方法
                    Method getter = property.getReadMethod();
                    Object value = getter.invoke(obj);
                    map.put(key, (String) value);
                }
            }
        } catch (Exception e) {
            System.out.println("transBean2Map Error " + e);
        }
        return map;
    }

    public static Map sign(UnionDto dto) {
        Map<String, String> srcMap = getRawData(dto);
        return srcMap;
    }

    public static Map getRawData(UnionDto superDto)  {
        Map<String, String> srcMap = getSrcMap(superDto);
        String json_data = JSON.toJSONString(srcMap);
        MessageDigest md = null;
        try {
            md = MessageDigest.getInstance("SHA-256");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        md.reset();
        try {
            md.update(json_data.getBytes("utf-8"));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        srcMap.put("sign_data",bytes2Hex(md.digest()));
        //加密
        String keyStr = key;
        byte key_byte[] = keyStr.getBytes();// 3DES 24 bytes key
        SecretKey k =  new SecretKeySpec(key_byte, "DESede");
        javax.crypto.Cipher cipher = null;
        try {
            cipher = javax.crypto.Cipher.getInstance("DESede/ECB/PKCS5Padding");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        }
        try {
            cipher.init(javax.crypto.Cipher.ENCRYPT_MODE, k);
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        }
        byte[] b= new byte[0];
        try {
            b = cipher.doFinal(json_data.getBytes("utf-8"));
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        srcMap.put("json_data",bytes2Hex(b));
        List<String> sortKeys = new ArrayList<String>(srcMap.keySet());
        Collections.sort(sortKeys);
        StringBuffer sb = new StringBuffer();
        for (String key : sortKeys) {
                sb.append(key);
                sb.append("=");
                sb.append(srcMap.get(key));
                sb.append("&");
        }
        String rawData = sb.toString();
        System.out.println(rawData.substring(0, rawData.length() - 1));
       // srcMap.put(SYS_VAR_RAW_DATA, rawData.substring(0, rawData.length() - 1));
        //srcMap.put("param",rawData.substring(0, rawData.length() - 1));
        return srcMap;
    }


    public static String bytes2Hex(byte[] bts) {
        return Hex.encodeHexString(bts);
    }


    /**
     * json字符串转为Object对象
     *
     * @param jsonStr
     * @param dtoClass
     * @param <T>
     * @return
     */
    public static <T> T jsonStrToDto(String jsonStr, Class<T> dtoClass) {
        try {
            Object dto;
            JSONObject jsonDto = JSONObject.fromObject(jsonStr);
            dto = JSONObject.toBean(jsonDto, dtoClass);
            return (T) dto;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    private static void ImageToBase64(String imgPath) {
        byte[] data = null;
        // 读取图片字节数组
        try {
            InputStream in = new FileInputStream(imgPath);
            data = new byte[in.available()];
            in.read(data);
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 对字节数组Base64编码
        BASE64Encoder encoder = new BASE64Encoder();
        // 返回Base64编码过的字节数组字符串
        System.out.println( encoder.encode(Objects.requireNonNull(data)));
    }

    public static void main(String[] args){
        ImageToBase64("/Users/dufei/Downloads/1.jpeg");

    }


}
